package wortubung;

import static wortubung.util.MatrixPrinter.*;
import static wortubung.util.CommonUtils.*;

import java.io.File;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import wortubung.core.LANG;
import wortubung.lang.LanguageManager;

// All date format: YYYY-MM-DD
public class PersonalStudy {

	public static class Item {
		private LANG   lang;
		private String[][] expressionMeanings;

		public Item(LANG lang, String[][] expressionMeanings) {
			this.lang = lang;
			this.expressionMeanings = expressionMeanings;
		}
		public LANG   getLang() { return lang; }
		public String[][] getExpressionMeanings() { return expressionMeanings; }
	}

	private static ArrayList<MonthlyCollection> list = new ArrayList<MonthlyCollection>();
	
	public static void addCollection(String month, File file) { list.add(new MonthlyCollection(month, file)); }

	public static void reset() { list.clear(); }

	public static void finish() {
		list.sort(new Comparator<MonthlyCollection>() {
			@Override public int compare(MonthlyCollection a, MonthlyCollection b) {
				return a.getMonth().compareTo(b.getMonth());
			}
		});
	}

	static DailyItems findDailyItems(String date) {
		for (MonthlyCollection mc : list)
			if (mc.containsDate(date))
				return mc.getDailyStudy(date);
		return null;
	}

	static MonthlyCollection findMonthlyCollections(String month) {
		for (MonthlyCollection mc : list)
			if (mc.getMonth().equals(month))
				return mc;
		return null;
	}

	// <[[YYYY-]MM-]DD>* - Print daily sentences for the day (if specified) or today.
    public static void doDaily(String params, WortUbung wortUbung) {
    	if (params != null && params.startsWith("list")) {
    		params = params.substring(4).trim();
    		doDailyList(params, wortUbung);
    		return;
    	}

    	if (isEmpty(params))
    		params = todayYYYYMMDD();

    	for (String d : params.split(" +")) {
    		String[] ymd = d.split("-");
    		switch (ymd.length) {
    		case 1: d = chopRight(todayYYYYMMDD(), 2) + d; break;
    		case 2:	d = getYear() + "-" + d; break;
    		}
    		DailyItems dailyItems = findDailyItems(d);
    		if (dailyItems == null) {
    			wortUbung.promptln("(No daily study found for " + d + ".)");
    			continue;
    		}

    		ArrayList<String> lines = new ArrayList<String>();
    		wortUbung.promptln("[" + dailyItems.date + ']');
    		wortUbung.promptln();
    		for (Item item : dailyItems) {
    			for (String[] exprMeaning : item.getExpressionMeanings()) {
    				lines.clear();
	    			wrapText(exprMeaning[0], wortUbung.getPageWidth(), lines);
	    			for (String line : lines)
	    				wortUbung.promptln(line);
    			}
    			wortUbung.promptln();
    		}
    	}
    }

    // list [<[YYYY-]MM>*|YYYY] (No leading "list" in params.)
    private static void doDailyList(String params, WortUbung wortUbung) {
    	String[] sa = params.split(" +");
    	trim(sa);
    	if (sa.length == 1 && sa[0].indexOf('-') < 0 && sa[0].length() == 4) {
    		String yr = sa[0];
    		sa = new String[]{ yr+"-01", yr+"-02", yr+"-03", yr+"-04", yr+"-05", yr+"-06",
    			               yr+"-07", yr+"-08", yr+"-09", yr+"-10", yr+"-11", yr+"-12" };
    	}

    	HashSet<LANG> langs = new HashSet<LANG>();
    	int totalDays = 0;
    	ArrayList<MonthlyCollection> list = new ArrayList<MonthlyCollection>();
    	for (String m : sa) {
    		if (!m.contains("-"))
    			m = getYear() + "-" + m;
    		MonthlyCollection mc = findMonthlyCollections(m);
    		if (mc != null) {
    			list.add(mc);
    			mc.getLanauges(langs);
    			totalDays += mc.numDaysWithStudy();
    		}
    	}

		LanguageManager[] lms = LanguageManager.getAllManagers(wortUbung);
		LANG lang;
		String[] titles = new String[1+langs.size()];
		int idx = 1;
    	for (LanguageManager lm : lms) {
    		lang = lm.getLanguage();
    		if (langs.contains(lang))
    			titles[idx++] = lang.name();
    	}

    	Object[][] content = new Object[totalDays][];
    	int recNum = 0;
    	for (MonthlyCollection mc : list) {
    		for (DailyItems di : mc.getDailyItemsList()) {
    			HashMap<LANG,Integer> dailyCounts = di.getCounts();
	    		content[recNum] = new Object[1+langs.size()];
	    		idx = 1;
	    		content[recNum][0] = di.date;
	        	for (LanguageManager lm : lms) {
	        		lang = lm.getLanguage();
	        		if (langs.contains(lang))
	        			content[recNum][idx++] = dailyCounts.get(lang);
	        	}
	        	++recNum;
        	}
    	}

    	if (isEmpty(content))
    		wortUbung.promptln("No daily items found for the " + (isEmpty(params) ? "current month" : "specified month(s)") + ".");
    	else
    		printMatrix(wortUbung, true, titles, content, false, true);
    }

} // end of PersonalStudy.


class DailyItems extends ArrayList<PersonalStudy.Item> {
	String date;
	DailyItems(String date) { this.date = date; }

	HashMap<LANG,Integer> getCounts() {
		HashMap<LANG,Integer> ret = new HashMap<LANG,Integer>();
		for (PersonalStudy.Item item : this)
			incCount(ret, item.getLang());
		return ret;
	}

} // end of class DailyItems.


class MonthlyCollection {
	private String month; // format: YYYY-MM
	private File file;
	private ArrayList<DailyItems> _dailyItemsList;

	MonthlyCollection(String month, File file) {
		this.month = month;
		this.file = file;
	}

	String getMonth() { return month; }

	boolean containsDate(String date) { return date.startsWith(month); }

	List<DailyItems> getDailyItemsList() {
		if (_dailyItemsList == null)
			load();
		return _dailyItemsList;
	}

	DailyItems getDailyStudy(String date) {
		for (DailyItems item : getDailyItemsList()) {
			if (item.date.equals(date))
				return item;
		}
		return null;
	}

	int numDaysWithStudy() {
		return getDailyItemsList().size();
	}

	void getLanauges(HashSet<LANG> set) {
		for (DailyItems item : getDailyItemsList())
			for (PersonalStudy.Item i : item)
				set.add(i.getLang());
	}

	// Sample file content:
	//
	// [2014-12-12]
	// {fr} Bonjour!   [Goodday!]
	//
	private void load() {
		_dailyItemsList = new ArrayList<DailyItems>();
		LineNumberReader br = null;
		try {
			br = openFile(file);
			DailyItems dailyItems = null;
			String line = br.readLine(); // first line
			while ((line = br.readLine()) != null) {
				line = line.trim();
				while (line.endsWith("\\")) {
					line = chopRight(line, 1);
					String tmp = br.readLine();
					if (tmp != null)
						line += tmp.trim();
				}
				if (isEmpty(line))
					continue;
				if (line.startsWith("[") && line.endsWith("]")) {
					dailyItems = new DailyItems(line.substring(1, line.length()-1).trim());
					_dailyItemsList.add(dailyItems);
					continue;
				}
				if (dailyItems == null)
					continue;
				if (line.startsWith("{")) {
					int idx = line.indexOf("}");
					if (idx <= 2)
						continue; // ignore
					LANG lang = LANG.guess(line.substring(1, idx).trim());
					if (lang == null)
						continue;
					line = line.substring(idx+1);
					String[] sa = line.split("\\$");
					String[][] exprMeanings = new String[sa.length][];
					int ptr = 0;
					for (String seg : sa) {
						idx = seg.indexOf("[");
						if (idx < 0) {
							exprMeanings[ptr] = new String[]{ seg.trim() };
						} else {
							String meaning = seg.substring(idx+1);
							seg = seg.substring(0, idx).trim();
							idx = meaning.indexOf("]");
							if (idx > 0)
								meaning = meaning.substring(0, idx).trim();
							exprMeanings[ptr] = new String[]{ seg, meaning };
						}
						++ptr;
					}
   					dailyItems.add(new PersonalStudy.Item(lang, exprMeanings));
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			try { br.close(); } catch(Exception e) {}
		}
	}

} // end of class MonthlyCollection.